1 Introduction

There are many presentation and drawing tools out there. And these allow the user full control over the diagram so generally result in prettier diagrams that can convey more information to the audience at that point in time.

But that point in time passes, and pretty pictures can quickly become out-of-date and, ironically, misinforming if they don’t match the reality of the system they are describing. This is especially so if one team is drawing the pretty pictures, and another team is writing the software/implementing the system.

Having diagrams as code that can live beside the system design/code, that the stakeholders are equally comfortable editing and viewing,reduces the gap i.e. “Where system diagrams meet system reality”.

We will “explore” two packages to do this: DiagrammeR and nomnoml. Each of these follows a specific grammar so that sets of “sentences” will morph into very different kinds of diagrams.

2 Using DiagrammeR

DiagrammeR is a unique package since it allows you create diagrams and the Network Diagrams that you have created using tidygraph and ggraph. And it uses the tidyverse pipe %>% syntax too! But that is for another time, or perhaps you ca explore this yourself!!

Graphviz support is an integral part of the DiagrammeR R package. It is another approach to creating diagrams using text. And hence the code you write is actually R code.

Here is the basic structure of a Graphviz code:

[strict] (graph | digraph) [ID] '{' stmt_list '}'
grViz("
digraph boxes_and_circles {

  # a 'graph' statement
  graph [overlap = true, fontsize = 10,forcelabels = true]

  # several 'node' statements
  node [shape = box,fontname = Helvetica, color = red, style = filled]
  A[label = 'This is \\n an internal \\n label', xlabel = 'This is \\nan external \\nlabel']; B; C; D; E; F

  node [shape = circle, fixedsize = true, color = palegreen, width = 0.9] // sets as circles
  1; 2; 3; 4; 5; 6; 7; 8

  # several 'edge' statements
  A->{1,2,3,4} B->2 B->3 B->4 C->A
  1->D E->A 2->4 1->5 1->F
  E->6 4->6 5->7 6->7 3->8 3->1
}
")

2.1 Sequence Diagram

2.2 Sequence Diagram-2

2.3 Sequence Diagram 3

2.4 Mindmap

2.5 Gantt Chart

2.6 Flow chart

3 Using nomnoml

nomnoml is touted as a “sassy” UML diagram creator, in R. It allows us to rapidly create many of diagrams that we can use in System Descriptions.

The syntax options for nomnoml and what can be created is described here https://nomnoml.com/

The R pdf Manual for nomnoml at CRAN ( read just the first half-page and you are ready!!)

So what can it do?

#import: filename
#arrowSize: 1
#bendSize: 0.3
#direction: down | right
#gutter: 5
#edgeMargin: 0
#gravity: 1
#edges: hard | rounded
#background: lightgrey

//nested list of colours
//#fill: #fcfcfc; #eee8d5; #fdf6e3
#fill: lightgreen; pink;
#fillArrows: false
#font: Calibri
#fontSize: 12
#leading: 1.25
#lineWidth: 3
#padding: 8
#spacing: 40
#stroke: #33322E
#title: filename
#zoom: 1
#acyclicer: greedy
#ranker: network-simplex | tight-tree | longest-path

[Pirate|eyeCount: Int|raid()|pillage()|
  [beard]--[parrot]
  [beard]-:>[foul mouth]
  ]

[<table>mischief | bawl | sing || yell | drink]

[<abstract>Marauder]<:--[Pirate]
[Pirate]- 0..7[mischief]
[jollyness]_>[Pirate]
[jollyness]->[rum]
[jollyness]->[singing]
[Pirate]-> *[rum|tastiness: Int|swig()]
[Pirate]->[singing]
[singing]<->[rum]

[<start>st]->[<state>plunder]
[plunder]->[<choice>more loot]
[more loot]->[st]
[more loot] no ->[<end>e]

[<actor>Sailor] - [<usecase>shiver me;timbers]

3.1 Some definitions on the “grammar of shapes” in nomnoml

  1. Association Types: Connectors between blocks( i.e. Classifiers)

  2. Classifier Types: Kinds of blocks.

  3. Directive Types: Directives change the nature of the diagram rendered, by affective parameters like colour, direction and margins. ( Ha! VC people!!)

CSS colours https://www.w3schools.com/cssref/css_colors.asp Only these colours are permitted, so use either the names or these specific colour hash codes. Any general hash code will not render.

//association-1
[a] - [b] 

//association-2
[b] -> [c] 

//association_3
[c] <-> [a]

//dependency-1
[a] <-->[d]

//dependency-2
#.ell: visual=ellipse fill=#fbfb09 bold
#.arvind: visual=rhomb fill=#ff2234 bold
[<ell>e]-->[a]
//generalization-1
[c]-:>[<arvind>k]

//implementation --:>
[k]--:>[d]
//composition +-
[a]+-[b]
//composition +->
[b]-+[c]
//aggregation o-
[c]o->[d]
//aggregation o->
[d]o->[a]
//note --
[d]--[everything happens;here]
//hidden -/-
[d]-/-[f]
////////////////////////
//weightless edge _>
//[k]_>[d] //not working
//weightless dashed__
//[d]__[j] //not working

3.1.1 Classifier Types

These are different kinds of blocks.

[class]->[<abstract> abstract]
[<abstract> abstract]-:>[<instance> instance]
[<instance> instance]-:>[<note> note]
[<note> note]-->[<reference> reference]
[<package> package|components]-->[<frame> frame|]
[<database> database]-->[<start> start]
[<end> end]-o>[<state> state]
[<choice> choice]--->[<sync> sync]
[<input> input]->[<sender> sender]
[<receiver> receiver]o-[<transceiver> transceiver]
#direction:down
#background:lightgrey
#fill: fuchsia; green; purple
#fillArrows: false
#font: Courier
[class]->[<abstract> abstract]
[<abstract> abstract]-:>[<instance> instance]
[<instance> instance]-:>[<note> note]
[<note> note]-->[<reference> reference]
#font: CenturySchoolbook
#fill: lightyellow
#stroke: green

[<actor> actor]---[<usecase> usecase]
[<usecase> usecase]<-->[<label> label]
[<usecase> usecase]-/-[<hidden> hidden]
[<table> table| a | 5 || b | 7]
[<table> table| c | 9 ]

3.2 Directives

Directives change the nature of the diagram rendered, by affective parameters like colour, direction and margins.

3.3 Custom classifier styles

A directive that starts with “.” define a classifier’s style. The style is written as a space separated list of modifiers and key/value pairs.

#.box: fill=#8f8 dashed
#.blob: visual=ellipse title=bold
#.arvind: visual=rhomb title=bold dashed fill=CornFlowerBlue
[<box> GreenBox]
[<blob> Blobby]
[<arvind> Someone]

3.4 nomnoml Key/value pairs

  • fill=(any css color)
  • stroke=(any css color)
  • align=center align=left
  • direction=right direction=down
  • visual=actor
  • visual=class
  • visual=database
  • visual=ellipse
  • visual=end
  • visual=frame
  • visual=hidden
  • visual=input
  • visual=none
  • visual=note
  • visual=package
  • visual=receiver
  • visual=rhomb
  • visual=roundrect
  • visual=sender
  • visual=start
  • visual=sync
  • visual=table
  • visual=transceiver

3.5 Text modifiers

bold center italic left underline

# .box: fill=#8f8 dashed
# .blob: visual=rhomb title=bold fill=#8f8 dashed

[A]-[B]
[B]--[<usecase>C]
[C]-[<box> D]
[B]--[<blob> Jabba;TheHut]
[a] ->[b]
[b] -:> [c]
[c]o->[d]
[d]-/-[e]
#fill: lightgreen; lightblue; lightyellow; grey; white

[<table> table | c | 9 ]

[R | [<table> Packages |
         Base R |
         [ <table> tidyverse| ggplot | tidyr | readr |
             [<table> dplyr|
                 magrittr | Others]]]]
#fill: lightgreen; lightblue; lightyellow; pink; white

[RStudio | [R | [<table> Packages |
                   Base R | [ tidyverse |
                               ggplot | tidyr | readr |
                               [dplyr]--[magrittr]
                               [dplyr]--[Others]
                             | tibble
                             ]
                 | lubridate | DiagrammeR | Lattice]]]
[Linux]+-[Ubuntu]
[Linux]+-[Mint]
[Ubuntu]--[Mint]
[Linux]+-[Rosa Linux]
[Linux]+-[Mx Linux]
[Debian]-+[Linux]


[Fedora]-+[Linux]
[Puppy Linux]-+[Linux]
[Personal Pups]-+[Puppy Linux]
LS0tDQp0aXRsZTogIlRoZSBHcmFtbWFyIG9mIERpYWdyYW1zIg0Kc3VidGl0bGU6ICIgQ29udmVydGluZyBUZXh0IHRvIERpYWdyYW1zIGluIFIiDQphdXRob3I6IEFydmluZCBWZW5rYXRhZHJpDQphZmZpbGlhdGlvbjogU3Jpc2h0aSBNYW5pcGFsIEluc3RpdHV0ZSBvZiBBcnQsIERlc2lnbiwgYW5kIFRlY2hub2xvZ3ksIEJhbmdhbG9yZQ0Kb3V0cHV0Og0KICBodG1sX2RvY3VtZW50Og0KICAgIHRoZW1lOiBmbGF0bHkNCiAgICB0b2M6IFRSVUUNCiAgICB0b2NfZmxvYXQ6IFRSVUUNCiAgICB0b2NfZGVwdGg6IDINCiAgICBudW1iZXJfc2VjdGlvbnM6IFRSVUUNCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUNCiAgICBjb2RlX2Rvd25sb2FkOiBUUlVFDQotLS0NCg0KIyBJbnRyb2R1Y3Rpb24NCg0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9DQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUsIG1lc3NhZ2UgPSBGQUxTRSkNCmxpYnJhcnkodGlkeXZlcnNlKQ0KDQpsaWJyYXJ5KERpYWdyYW1tZVIpDQpsaWJyYXJ5KG5vbW5vbWwpDQpgYGANCg0KVGhlcmUgYXJlIG1hbnkgcHJlc2VudGF0aW9uIGFuZCBkcmF3aW5nIHRvb2xzIG91dCB0aGVyZS4gQW5kIHRoZXNlIGFsbG93IHRoZSB1c2VyIGZ1bGwgY29udHJvbCBvdmVyIHRoZSBkaWFncmFtIHNvIGdlbmVyYWxseSByZXN1bHQgaW4gcHJldHRpZXIgZGlhZ3JhbXMgdGhhdCBjYW4gY29udmV5IG1vcmUgaW5mb3JtYXRpb24gdG8gdGhlIGF1ZGllbmNlIGF0IHRoYXQgcG9pbnQgaW4gdGltZS4NCg0KQnV0IHRoYXQgcG9pbnQgaW4gdGltZSBwYXNzZXMsIGFuZCAqKnByZXR0eSBwaWN0dXJlcyBjYW4gcXVpY2tseSBiZWNvbWUgb3V0LW9mLWRhdGUqKiBhbmQsIGlyb25pY2FsbHksIG1pc2luZm9ybWluZyBpZiB0aGV5IGRvbid0IG1hdGNoIHRoZSByZWFsaXR5IG9mIHRoZSBzeXN0ZW0gdGhleSBhcmUgZGVzY3JpYmluZy4gVGhpcyBpcyBlc3BlY2lhbGx5IHNvIGlmIG9uZSB0ZWFtIGlzIGRyYXdpbmcgdGhlIHByZXR0eSBwaWN0dXJlcywgYW5kIGFub3RoZXIgdGVhbSBpcyB3cml0aW5nIHRoZSBzb2Z0d2FyZS9pbXBsZW1lbnRpbmcgdGhlIHN5c3RlbS4NCg0KSGF2aW5nICoqZGlhZ3JhbXMgYXMgY29kZSB0aGF0IGNhbiBsaXZlIGJlc2lkZSB0aGUgc3lzdGVtIGRlc2lnbi9jb2RlKiosIHRoYXQgdGhlIHN0YWtlaG9sZGVycyBhcmUgZXF1YWxseSBjb21mb3J0YWJsZSBlZGl0aW5nIGFuZCB2aWV3aW5nLHJlZHVjZXMgdGhlIGdhcCBpLmUuICJXaGVyZSBzeXN0ZW0gZGlhZ3JhbXMgbWVldCBzeXN0ZW0gcmVhbGl0eSIuDQoNCldlIHdpbGwgImV4cGxvcmUiIHR3byBwYWNrYWdlcyB0byBkbyB0aGlzOiBgRGlhZ3JhbW1lUmANCmFuZCBgbm9tbm9tbGAuIEVhY2ggb2YgdGhlc2UgZm9sbG93cyBhIHNwZWNpZmljIGdyYW1tYXIgc28gdGhhdCBzZXRzIG9mICJzZW50ZW5jZXMiIHdpbGwgbW9ycGggaW50byB2ZXJ5IGRpZmZlcmVudCBraW5kcyBvZiBkaWFncmFtcy4NCg0KDQoNCg0KIyBVc2luZyBEaWFncmFtbWVSDQoNCmBEaWFncmFtbWVSYCBpcyBhIHVuaXF1ZSBwYWNrYWdlIHNpbmNlIGl0IGFsbG93cyB5b3UgY3JlYXRlIGRpYWdyYW1zICoqYW5kKiogdGhlIE5ldHdvcmsgRGlhZ3JhbXMgdGhhdCB5b3UgaGF2ZSBjcmVhdGVkIHVzaW5nIGB0aWR5Z3JhcGhgIGFuZCBgZ2dyYXBoYC4gQW5kIGl0IHVzZXMgdGhlIHRpZHl2ZXJzZSBwaXBlIGAlPiVgIHN5bnRheCB0b28hIEJ1dCB0aGF0IGlzIGZvciBhbm90aGVyIHRpbWUsIG9yIHBlcmhhcHMgeW91IGNhIGV4cGxvcmUgdGhpcyB5b3Vyc2VsZiEhDQoNCg0KKipHcmFwaHZpeioqIHN1cHBvcnQgaXMgYW4gaW50ZWdyYWwgcGFydCBvZiB0aGUgYERpYWdyYW1tZVJgIFIgcGFja2FnZS4gSXQgaXMgYW5vdGhlciBhcHByb2FjaCB0byBjcmVhdGluZyBkaWFncmFtcyB1c2luZyB0ZXh0LiBBbmQgaGVuY2UgdGhlIGNvZGUgeW91IHdyaXRlIGlzIGFjdHVhbGx5IFIgY29kZS4NCg0KSGVyZSBpcyB0aGUgYmFzaWMgc3RydWN0dXJlIG9mIGEgYEdyYXBodml6YCBjb2RlOg0KDQogICAgW3N0cmljdF0gKGdyYXBoIHwgZGlncmFwaCkgW0lEXSAneycgc3RtdF9saXN0ICd9Jw0KDQpgYGB7ciBEaWFncmFtbWVSLCBmaWcud2lkdGg9NywgZmlnLmhlaWdodD0gOCwgZmlnLmFsaWduPSdjZW50ZXInfQ0KDQpnclZpeigiDQpkaWdyYXBoIGJveGVzX2FuZF9jaXJjbGVzIHsNCg0KICAjIGEgJ2dyYXBoJyBzdGF0ZW1lbnQNCiAgZ3JhcGggW292ZXJsYXAgPSB0cnVlLCBmb250c2l6ZSA9IDEwLGZvcmNlbGFiZWxzID0gdHJ1ZV0NCg0KICAjIHNldmVyYWwgJ25vZGUnIHN0YXRlbWVudHMNCiAgbm9kZSBbc2hhcGUgPSBib3gsZm9udG5hbWUgPSBIZWx2ZXRpY2EsIGNvbG9yID0gcmVkLCBzdHlsZSA9IGZpbGxlZF0NCiAgQVtsYWJlbCA9ICdUaGlzIGlzIFxcbiBhbiBpbnRlcm5hbCBcXG4gbGFiZWwnLCB4bGFiZWwgPSAnVGhpcyBpcyBcXG5hbiBleHRlcm5hbCBcXG5sYWJlbCddOyBCOyBDOyBEOyBFOyBGDQoNCiAgbm9kZSBbc2hhcGUgPSBjaXJjbGUsIGZpeGVkc2l6ZSA9IHRydWUsIGNvbG9yID0gcGFsZWdyZWVuLCB3aWR0aCA9IDAuOV0gLy8gc2V0cyBhcyBjaXJjbGVzDQogIDE7IDI7IDM7IDQ7IDU7IDY7IDc7IDgNCg0KICAjIHNldmVyYWwgJ2VkZ2UnIHN0YXRlbWVudHMNCiAgQS0+ezEsMiwzLDR9IEItPjIgQi0+MyBCLT40IEMtPkENCiAgMS0+RCBFLT5BIDItPjQgMS0+NSAxLT5GDQogIEUtPjYgNC0+NiA1LT43IDYtPjcgMy0+OCAzLT4xDQp9DQoiKQ0KYGBgDQoNCg0KIyMgU2VxdWVuY2UgRGlhZ3JhbQ0KDQojIyBTZXF1ZW5jZSBEaWFncmFtLTINCg0KIyMgU2VxdWVuY2UgRGlhZ3JhbSAzDQoNCiMjIE1pbmRtYXANCg0KDQoNCiMjIEdhbnR0IENoYXJ0DQoNCg0KDQojIyBGbG93IGNoYXJ0DQoNCg0KDQoNCg0KDQojIFVzaW5nIGBub21ub21sYA0KDQpgbm9tbm9tbGAgaXMgdG91dGVkIGFzIGEgInNhc3N5IiBVTUwgZGlhZ3JhbSBjcmVhdG9yLCBpbiBSLiBJdCBhbGxvd3MgdXMNCnRvIHJhcGlkbHkgY3JlYXRlIG1hbnkgb2YgZGlhZ3JhbXMgdGhhdCB3ZSBjYW4gdXNlIGluIFN5c3RlbSBEZXNjcmlwdGlvbnMuDQoNClRoZSBzeW50YXggb3B0aW9ucyBmb3Igbm9tbm9tbCBhbmQgd2hhdCBjYW4gYmUgY3JlYXRlZCBpcyBkZXNjcmliZWQgaGVyZQ0KPGh0dHBzOi8vbm9tbm9tbC5jb20vPg0KDQpUaGUgUiBwZGYgTWFudWFsIGZvciBub21ub21sIGF0DQpbQ1JBTl0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL25vbW5vbWwvbm9tbm9tbC5wZGYpICgNCnJlYWQganVzdCB0aGUgZmlyc3QgaGFsZi1wYWdlIGFuZCB5b3UgYXJlIHJlYWR5ISEpDQoNClNvIHdoYXQgY2FuIGl0IGRvPw0KDQpgYGB7bm9tbm9tbH0NCiNpbXBvcnQ6IGZpbGVuYW1lDQojYXJyb3dTaXplOiAxDQojYmVuZFNpemU6IDAuMw0KI2RpcmVjdGlvbjogZG93biB8IHJpZ2h0DQojZ3V0dGVyOiA1DQojZWRnZU1hcmdpbjogMA0KI2dyYXZpdHk6IDENCiNlZGdlczogaGFyZCB8IHJvdW5kZWQNCiNiYWNrZ3JvdW5kOiBsaWdodGdyZXkNCg0KLy9uZXN0ZWQgbGlzdCBvZiBjb2xvdXJzDQovLyNmaWxsOiAjZmNmY2ZjOyAjZWVlOGQ1OyAjZmRmNmUzDQojZmlsbDogbGlnaHRncmVlbjsgcGluazsNCiNmaWxsQXJyb3dzOiBmYWxzZQ0KI2ZvbnQ6IENhbGlicmkNCiNmb250U2l6ZTogMTINCiNsZWFkaW5nOiAxLjI1DQojbGluZVdpZHRoOiAzDQojcGFkZGluZzogOA0KI3NwYWNpbmc6IDQwDQojc3Ryb2tlOiAjMzMzMjJFDQojdGl0bGU6IGZpbGVuYW1lDQojem9vbTogMQ0KI2FjeWNsaWNlcjogZ3JlZWR5DQojcmFua2VyOiBuZXR3b3JrLXNpbXBsZXggfCB0aWdodC10cmVlIHwgbG9uZ2VzdC1wYXRoDQoNCltQaXJhdGV8ZXllQ291bnQ6IEludHxyYWlkKCl8cGlsbGFnZSgpfA0KICBbYmVhcmRdLS1bcGFycm90XQ0KICBbYmVhcmRdLTo+W2ZvdWwgbW91dGhdDQogIF0NCg0KWzx0YWJsZT5taXNjaGllZiB8IGJhd2wgfCBzaW5nIHx8IHllbGwgfCBkcmlua10NCg0KWzxhYnN0cmFjdD5NYXJhdWRlcl08Oi0tW1BpcmF0ZV0NCltQaXJhdGVdLSAwLi43W21pc2NoaWVmXQ0KW2pvbGx5bmVzc11fPltQaXJhdGVdDQpbam9sbHluZXNzXS0+W3J1bV0NCltqb2xseW5lc3NdLT5bc2luZ2luZ10NCltQaXJhdGVdLT4gKltydW18dGFzdGluZXNzOiBJbnR8c3dpZygpXQ0KW1BpcmF0ZV0tPltzaW5naW5nXQ0KW3NpbmdpbmddPC0+W3J1bV0NCg0KWzxzdGFydD5zdF0tPls8c3RhdGU+cGx1bmRlcl0NCltwbHVuZGVyXS0+WzxjaG9pY2U+bW9yZSBsb290XQ0KW21vcmUgbG9vdF0tPltzdF0NClttb3JlIGxvb3RdIG5vIC0+WzxlbmQ+ZV0NCg0KWzxhY3Rvcj5TYWlsb3JdIC0gWzx1c2VjYXNlPnNoaXZlciBtZTt0aW1iZXJzXQ0KYGBgDQoNCiMjIFNvbWUgZGVmaW5pdGlvbnMgb24gdGhlICJncmFtbWFyIG9mIHNoYXBlcyIgaW4gYG5vbW5vbWxgDQoNCjEuICBBc3NvY2lhdGlvbiBUeXBlczogQ29ubmVjdG9ycyBiZXR3ZWVuIGJsb2NrcyggaS5lLiBDbGFzc2lmaWVycykNCg0KMi4gIENsYXNzaWZpZXIgVHlwZXM6IEtpbmRzIG9mICoqYmxvY2tzKiouDQoNCjMuICBEaXJlY3RpdmUgVHlwZXM6IERpcmVjdGl2ZXMgY2hhbmdlIHRoZSBuYXR1cmUgb2YgdGhlIGRpYWdyYW0NCiAgICByZW5kZXJlZCwgYnkgYWZmZWN0aXZlIHBhcmFtZXRlcnMgbGlrZSBjb2xvdXIsIGRpcmVjdGlvbiBhbmQNCiAgICBtYXJnaW5zLiAoIEhhISBWQyBwZW9wbGUhISkNCg0KQ1NTIGNvbG91cnMgPGh0dHBzOi8vd3d3Lnczc2Nob29scy5jb20vY3NzcmVmL2Nzc19jb2xvcnMuYXNwPiBPbmx5IHRoZXNlDQpjb2xvdXJzIGFyZSBwZXJtaXR0ZWQsIHNvIHVzZSBlaXRoZXIgdGhlIG5hbWVzIG9yIHRoZXNlIHNwZWNpZmljIGNvbG91cg0KaGFzaCBjb2Rlcy4gQW55IGdlbmVyYWwgaGFzaCBjb2RlIHdpbGwgKm5vdCogcmVuZGVyLg0KDQpgYGB7bm9tbm9tbCBhc3NvY2lhdGlvbi0xfQ0KLy9hc3NvY2lhdGlvbi0xDQpbYV0gLSBbYl0gDQoNCi8vYXNzb2NpYXRpb24tMg0KW2JdIC0+IFtjXSANCg0KLy9hc3NvY2lhdGlvbl8zDQpbY10gPC0+IFthXQ0KDQovL2RlcGVuZGVuY3ktMQ0KW2FdIDwtLT5bZF0NCg0KLy9kZXBlbmRlbmN5LTINCiMuZWxsOiB2aXN1YWw9ZWxsaXBzZSBmaWxsPSNmYmZiMDkgYm9sZA0KIy5hcnZpbmQ6IHZpc3VhbD1yaG9tYiBmaWxsPSNmZjIyMzQgYm9sZA0KWzxlbGw+ZV0tLT5bYV0NCi8vZ2VuZXJhbGl6YXRpb24tMQ0KW2NdLTo+WzxhcnZpbmQ+a10NCg0KLy9pbXBsZW1lbnRhdGlvbiAtLTo+DQpba10tLTo+W2RdDQpgYGANCg0KYGBge25vbW5vbWwgYXNzb2NpYXRpb24tMixzdmc9VFJVRX0NCi8vY29tcG9zaXRpb24gKy0NClthXSstW2JdDQovL2NvbXBvc2l0aW9uICstPg0KW2JdLStbY10NCi8vYWdncmVnYXRpb24gby0NCltjXW8tPltkXQ0KLy9hZ2dyZWdhdGlvbiBvLT4NCltkXW8tPlthXQ0KLy9ub3RlIC0tDQpbZF0tLVtldmVyeXRoaW5nIGhhcHBlbnM7aGVyZV0NCi8vaGlkZGVuIC0vLQ0KW2RdLS8tW2ZdDQovLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8NCi8vd2VpZ2h0bGVzcyBlZGdlIF8+DQovL1trXV8+W2RdIC8vbm90IHdvcmtpbmcNCi8vd2VpZ2h0bGVzcyBkYXNoZWRfXw0KLy9bZF1fX1tqXSAvL25vdCB3b3JraW5nDQpgYGANCg0KIyMjIENsYXNzaWZpZXIgVHlwZXMNCg0KVGhlc2UgYXJlIGRpZmZlcmVudCBraW5kcyBvZiAqKmJsb2NrcyoqLg0KDQpgYGB7bm9tbm9tbCwgc3ZnPVRSVUV9DQpbY2xhc3NdLT5bPGFic3RyYWN0PiBhYnN0cmFjdF0NCls8YWJzdHJhY3Q+IGFic3RyYWN0XS06Pls8aW5zdGFuY2U+IGluc3RhbmNlXQ0KWzxpbnN0YW5jZT4gaW5zdGFuY2VdLTo+Wzxub3RlPiBub3RlXQ0KWzxub3RlPiBub3RlXS0tPls8cmVmZXJlbmNlPiByZWZlcmVuY2VdDQpgYGANCg0KYGBge25vbW5vbWx9DQpbPHBhY2thZ2U+IHBhY2thZ2V8Y29tcG9uZW50c10tLT5bPGZyYW1lPiBmcmFtZXxdDQpbPGRhdGFiYXNlPiBkYXRhYmFzZV0tLT5bPHN0YXJ0PiBzdGFydF0NCls8ZW5kPiBlbmRdLW8+WzxzdGF0ZT4gc3RhdGVdDQpgYGANCg0KYGBge25vbW5vbWx9DQpbPGNob2ljZT4gY2hvaWNlXS0tLT5bPHN5bmM+IHN5bmNdDQpbPGlucHV0PiBpbnB1dF0tPls8c2VuZGVyPiBzZW5kZXJdDQpbPHJlY2VpdmVyPiByZWNlaXZlcl1vLVs8dHJhbnNjZWl2ZXI+IHRyYW5zY2VpdmVyXQ0KYGBgDQoNCmBgYHtub21ub21sLCBzdmc9VFJVRX0NCiNkaXJlY3Rpb246ZG93bg0KI2JhY2tncm91bmQ6bGlnaHRncmV5DQojZmlsbDogZnVjaHNpYTsgZ3JlZW47IHB1cnBsZQ0KI2ZpbGxBcnJvd3M6IGZhbHNlDQojZm9udDogQ291cmllcg0KW2NsYXNzXS0+WzxhYnN0cmFjdD4gYWJzdHJhY3RdDQpbPGFic3RyYWN0PiBhYnN0cmFjdF0tOj5bPGluc3RhbmNlPiBpbnN0YW5jZV0NCls8aW5zdGFuY2U+IGluc3RhbmNlXS06Pls8bm90ZT4gbm90ZV0NCls8bm90ZT4gbm90ZV0tLT5bPHJlZmVyZW5jZT4gcmVmZXJlbmNlXQ0KYGBgDQoNCmBgYHtub21ub21sfQ0KI2ZvbnQ6IENlbnR1cnlTY2hvb2xib29rDQojZmlsbDogbGlnaHR5ZWxsb3cNCiNzdHJva2U6IGdyZWVuDQoNCls8YWN0b3I+IGFjdG9yXS0tLVs8dXNlY2FzZT4gdXNlY2FzZV0NCls8dXNlY2FzZT4gdXNlY2FzZV08LS0+WzxsYWJlbD4gbGFiZWxdDQpbPHVzZWNhc2U+IHVzZWNhc2VdLS8tWzxoaWRkZW4+IGhpZGRlbl0NCmBgYA0KDQpgYGB7bm9tbm9tbH0NCls8dGFibGU+IHRhYmxlfCBhIHwgNSB8fCBiIHwgN10NCmBgYA0KDQpgYGB7bm9tbm9tbH0NCls8dGFibGU+IHRhYmxlfCBjIHwgOSBdDQpgYGANCg0KIyMgRGlyZWN0aXZlcw0KDQpEaXJlY3RpdmVzIGNoYW5nZSB0aGUgbmF0dXJlIG9mIHRoZSBkaWFncmFtIHJlbmRlcmVkLCBieSBhZmZlY3RpdmUNCnBhcmFtZXRlcnMgbGlrZSBjb2xvdXIsIGRpcmVjdGlvbiBhbmQgbWFyZ2lucy4NCg0KIyMgQ3VzdG9tIGNsYXNzaWZpZXIgc3R5bGVzDQoNCkEgZGlyZWN0aXZlIHRoYXQgc3RhcnRzIHdpdGggIi4iIGRlZmluZSBhICoqY2xhc3NpZmllcidzIHN0eWxlKiouIFRoZQ0Kc3R5bGUgaXMgd3JpdHRlbiBhcyBhIHNwYWNlIHNlcGFyYXRlZCBsaXN0IG9mICptb2RpZmllcnMqIGFuZCAqa2V5L3ZhbHVlDQpwYWlycyouDQoNCmBgYHtub21ub21sfQ0KIy5ib3g6IGZpbGw9IzhmOCBkYXNoZWQNCiMuYmxvYjogdmlzdWFsPWVsbGlwc2UgdGl0bGU9Ym9sZA0KIy5hcnZpbmQ6IHZpc3VhbD1yaG9tYiB0aXRsZT1ib2xkIGRhc2hlZCBmaWxsPUNvcm5GbG93ZXJCbHVlDQpbPGJveD4gR3JlZW5Cb3hdDQpbPGJsb2I+IEJsb2JieV0NCls8YXJ2aW5kPiBTb21lb25lXQ0KYGBgDQoNCiMjIGBub21ub21sYCBLZXkvdmFsdWUgcGFpcnMNCg0KLSAgIGZpbGw9KGFueSBjc3MgY29sb3IpDQotICAgc3Ryb2tlPShhbnkgY3NzIGNvbG9yKQ0KLSAgIGFsaWduPWNlbnRlciBhbGlnbj1sZWZ0DQotICAgZGlyZWN0aW9uPXJpZ2h0IGRpcmVjdGlvbj1kb3duDQotICAgdmlzdWFsPWFjdG9yDQotICAgdmlzdWFsPWNsYXNzDQotICAgdmlzdWFsPWRhdGFiYXNlDQotICAgdmlzdWFsPWVsbGlwc2UNCi0gICB2aXN1YWw9ZW5kDQotICAgdmlzdWFsPWZyYW1lDQotICAgdmlzdWFsPWhpZGRlbg0KLSAgIHZpc3VhbD1pbnB1dA0KLSAgIHZpc3VhbD1ub25lDQotICAgdmlzdWFsPW5vdGUNCi0gICB2aXN1YWw9cGFja2FnZQ0KLSAgIHZpc3VhbD1yZWNlaXZlcg0KLSAgIHZpc3VhbD1yaG9tYg0KLSAgIHZpc3VhbD1yb3VuZHJlY3QNCi0gICB2aXN1YWw9c2VuZGVyDQotICAgdmlzdWFsPXN0YXJ0DQotICAgdmlzdWFsPXN5bmMNCi0gICB2aXN1YWw9dGFibGUNCi0gICB2aXN1YWw9dHJhbnNjZWl2ZXINCg0KIyMgVGV4dCBtb2RpZmllcnMNCg0KYm9sZCBjZW50ZXIgaXRhbGljIGxlZnQgdW5kZXJsaW5lDQoNCmBgYHtub21ub21sfQ0KIyAuYm94OiBmaWxsPSM4ZjggZGFzaGVkDQojIC5ibG9iOiB2aXN1YWw9cmhvbWIgdGl0bGU9Ym9sZCBmaWxsPSM4ZjggZGFzaGVkDQoNCltBXS1bQl0NCltCXS0tWzx1c2VjYXNlPkNdDQpbQ10tWzxib3g+IERdDQpbQl0tLVs8YmxvYj4gSmFiYmE7VGhlSHV0XQ0KYGBgDQoNCmBgYHtub21ub21sfQ0KW2FdIC0+W2JdDQpbYl0gLTo+IFtjXQ0KW2Ndby0+W2RdDQpbZF0tLy1bZV0NCmBgYA0KDQpgYGB7bm9tbm9tbH0NCiNmaWxsOiBsaWdodGdyZWVuOyBsaWdodGJsdWU7IGxpZ2h0eWVsbG93OyBncmV5OyB3aGl0ZQ0KDQpbPHRhYmxlPiB0YWJsZSB8IGMgfCA5IF0NCg0KW1IgfCBbPHRhYmxlPiBQYWNrYWdlcyB8DQogICAgICAgICBCYXNlIFIgfA0KICAgICAgICAgWyA8dGFibGU+IHRpZHl2ZXJzZXwgZ2dwbG90IHwgdGlkeXIgfCByZWFkciB8DQogICAgICAgICAgICAgWzx0YWJsZT4gZHBseXJ8DQogICAgICAgICAgICAgICAgIG1hZ3JpdHRyIHwgT3RoZXJzXV1dXQ0KYGBgDQoNCmBgYHtub21ub21sfQ0KI2ZpbGw6IGxpZ2h0Z3JlZW47IGxpZ2h0Ymx1ZTsgbGlnaHR5ZWxsb3c7IHBpbms7IHdoaXRlDQoNCltSU3R1ZGlvIHwgW1IgfCBbPHRhYmxlPiBQYWNrYWdlcyB8DQogICAgICAgICAgICAgICAgICAgQmFzZSBSIHwgWyB0aWR5dmVyc2UgfA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdncGxvdCB8IHRpZHlyIHwgcmVhZHIgfA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtkcGx5cl0tLVttYWdyaXR0cl0NCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbZHBseXJdLS1bT3RoZXJzXQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8IHRpYmJsZQ0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBdDQogICAgICAgICAgICAgICAgIHwgbHVicmlkYXRlIHwgRGlhZ3JhbW1lUiB8IExhdHRpY2VdXV0NCmBgYA0KDQpgYGB7bm9tbm9tbCBtaW5kbWFwfQ0KW0xpbnV4XSstW1VidW50dV0NCltMaW51eF0rLVtNaW50XQ0KW1VidW50dV0tLVtNaW50XQ0KW0xpbnV4XSstW1Jvc2EgTGludXhdDQpbTGludXhdKy1bTXggTGludXhdDQpbRGViaWFuXS0rW0xpbnV4XQ0KDQoNCltGZWRvcmFdLStbTGludXhdDQpbUHVwcHkgTGludXhdLStbTGludXhdDQpbUGVyc29uYWwgUHVwc10tK1tQdXBweSBMaW51eF0NCg0KYGBgDQo=